package com.atguigu.spzx.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.model.vo.h5.CategoryVo;
import com.atguigu.spzx.product.mapper.CategoryMapper;
import com.atguigu.spzx.product.service.CategoryService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl implements CategoryService {
    @Resource
    CategoryMapper categoryMapper;
//    @Resource
//    StringRedisTemplate stringRedisTemplate;
    @Resource
    RedisTemplate redisTemplate;
//    @CachePut 只负责保存缓存  一般新增时使用(使用较少)
//    @CacheEvict 负责移除缓存  一般增删改时使用(使用较多：为了保证数据一致性-  mysql和redis的数据一致)
//    @Cacheable 先查询有缓存返回，没有缓存执行业务方法保存结果到缓存 使用多（在查询业务方法上使用）

    //value代表拼接的键的前缀 ， key代表拼接键的后面的内容：  可以使用形参变量名获取参数值、也可以加引号写字符串
    @Cacheable(value = "product:cates"  , key = "'all'") // product:cates::all
//    unless = "#result.size()==0 ")//unless: 指定不缓存的条件  #result代表方法的返回结果
    //#result.size()==0 表示返回结果集长度为0时 不缓存
    @Override
    public List<CategoryVo> findCategoryTree() {
        //查询所有的category集合 然后在业务中组装为父子集合
        List<CategoryVo> categories = categoryMapper.findAll();
        //挑选出所有的一级分类
        List<CategoryVo> parents = categories.stream()
                .filter(category -> category.getParentId().longValue() == 0L)
                .collect(Collectors.toList());
        buildTree(categories , parents);
        return parents;
    }

//    @Override
//    public List<CategoryVo> findCategoryTree() {
//        //== 1、查询分类的缓存
//        // 查询到直接返回
//        Object obj = redisTemplate.opsForValue().get("product:categories:all");
//        if(obj!=null){
//            return (List<CategoryVo>) obj;
//        }
////        String categoriesJson = stringRedisTemplate.opsForValue().get("product:categories:all");
////        if(!StringUtils.isEmpty(categoriesJson)){
////            return JSON.parseArray(categoriesJson ,CategoryVo.class);
////        }
//
//        //==2、没有缓存 查询数据库 存到缓存中
//        //查询所有的category集合 然后在业务中组装为父子集合
//        List<CategoryVo> categories = categoryMapper.findAll();
//        //挑选出所有的一级分类
//        List<CategoryVo> parents = categories.stream()
//                .filter(category -> category.getParentId().longValue() == 0L)
//                .collect(Collectors.toList());
////        if (buildTree(categories, parents)) return null;
//
//        buildTree(categories , parents);
//
////        stringRedisTemplate.opsForValue().set("product:categories:all",
////                JSON.toJSONString(parents),600 , TimeUnit.SECONDS);
//        redisTemplate.opsForValue().set("product:categories:all",
//                parents ,600 , TimeUnit.SECONDS );
//        return parents;
//    }

    private  void buildTree(List<CategoryVo> categories, List<CategoryVo> parents) {
        if(CollectionUtils.isEmpty(parents)){
            return;
        }
        //为每个一级分类挑选他的二级分类集合
        parents.forEach(parent->{
            List<CategoryVo> children = categories.stream().filter(child -> child.getParentId().equals(parent.getId())).collect(Collectors.toList());
            parent.setHasChildren(CollectionUtils.isEmpty(children)?false:true);
            parent.setChildren(children);
            //再将children当成父分类集合 从categories中查找他的子分类集合
            buildTree(categories , children);
        });
    }
}
